package com.zhentao;

import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTCreator;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.interfaces.Claim;
import com.auth0.jwt.interfaces.DecodedJWT;

import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * 用于生成Token和校验Token
 */
public class JWTUtil {

    private static final String SECRET_KEY = "abc123";//密钥

    /**
     * 生成Token
     */
    public static String generateToken(Map<String, String> userData){
        JWTCreator.Builder builder = JWT.create();
        // Payload
        for(Map.Entry<String,String> entry : userData.entrySet()){
            builder.withClaim(entry.getKey(),entry.getValue());
        }
        /**
         * token过期时间
         */
        Calendar calendar = Calendar.getInstance();
        //当前时间+30分钟
        //calendar.add(Calendar.MINUTE, 30);
        calendar.add(Calendar.DAY_OF_YEAR, 7);
        Date expiresTime = calendar.getTime();
        /**
         *  默认的Header是
         *   "typ": "JWT",
         *   "alg": "RS256"
         */
        //builder.withHeader(new HashMap<>());// Header
        builder.withExpiresAt(expiresTime);  // 过期时间

        String token = builder.sign(Algorithm.HMAC256(SECRET_KEY));//签名用的密钥

        //System.out.println(token);
        return token;
    }


    /**
     * 将Map<String, Claim>转为Map<String, String>
     */
    public static Map<String, String> payloadToStringMap(Map<String, Claim> payload){
        Map<String, String> userData = new HashMap<>();
        for(Map.Entry<String, Claim> entry : payload.entrySet()){
            userData.put(entry.getKey(),entry.getValue().asString());
        }
        return userData;
    }

    /**
     * 解析Token
     * 要求token必须是有效的（我们签发的）
     */
    public static Map<String,Claim> resolveToken(String token){
        // 创建解析对象，使用的算法和secret要与创建token时保持一致
        JWTVerifier jwtVerifier = JWT.require(Algorithm.HMAC256(SECRET_KEY)).build();
        // 解析指定的token
        DecodedJWT decodedJWT = jwtVerifier.verify(token);
        // 获取解析后的token中的payload信息
       /* Claim userId = decodedJWT.getClaim("userId");
        Claim userName = decodedJWT.getClaim("userName");
        System.out.println(userId.asInt());
        System.out.println(userName.asString());*/
        //输出超时时间
        //Date expiredTime = decodedJWT.getExpiresAt();
        //System.out.println("超期时间：" + expiredTime);
        return decodedJWT.getClaims();
    }
    /**
     * 从token中取用户ID
     * 要求token必须是有效的（我们签发的）
     * @return
     */
    public static String getUserIDWithToken(String token){
        Map<String, Claim> payload = JWTUtil.resolveToken(token);
        return payload.get("merchantId").asString();
    }

    /**
     * 从token中取用户ID
     * 不做验签，直接取
     */
    public static String getUserIDWithOutSignature(String token){
        DecodedJWT decodedJWT = JWT.decode(token);
        return decodedJWT.getClaim("merchantId").asString();
    }

    /**
     * 令牌自动续约
     * 只有在过期不到半小时内可以续约成功
     * 续约成功返回新的token，否则返回null
     */
    public static String autoContract(String token){
        //令牌解码
        DecodedJWT decodedJWT = JWT.decode(token);
        //获得令牌的过期时间
        Date expiredTime = decodedJWT.getExpiresAt();
        //当前时间-过期时间是否小于30分钟
        String newToken = null;
        if(new Date().getTime() - expiredTime.getTime() < 1300 * 60 * 1000){
            //重新签发
            newToken = generateToken(payloadToStringMap(decodedJWT.getClaims()));
        }
        return newToken;
    }

    /**
     * 从token中取值
     * 不做验签，直接取
     */
    public static String getValueWithOutSignature(String token,String key){
        DecodedJWT decodedJWT = JWT.decode(token);
        return decodedJWT.getClaim(key).asString();
    }

    /**
     * 从token中取用户后端权限
     * 不做验签，直接取
     */
    public static String getUserAuthURLWithOutSignature(String token){
        return getValueWithOutSignature(token,"apiUrl");
    }

    /**
     * 从token中取过期时间
     * 不做验签，直接取
     */
    public static Long getExpWithOutSignature(String token){
        DecodedJWT decodedJWT = JWT.decode(token);
        return decodedJWT.getClaim("exp").asLong();
    }



    public static void main(String[] args)throws Exception {
        String ss=MD5Utils.encodeWithSalt("123456","盐1");
        System.out.println(ss);
        /*Map<String, String> userData = new HashMap<>();
        userData.put("userId","1");
        userData.put("userName","yujinxiang");

        String token = generateToken(userData);
        System.out.println(token);*/
       /* Map<String,Claim> map = null;
        try {
            map = resolveToken("eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c");
        } catch (TokenExpiredException e) {
            e.printStackTrace();
        }
        System.out.println(map.get("uid").asString());*/
        //System.out.println(getUserIDWithToken("eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1aWQiOiIxIiwiZXhwIjoxNjUzNDAyMTA3fQ._Y37Z3W0RWXxQHab1f5tPZDvHcp_rQtGFj8aQfn04No"));
       // System.out.println(getUserIDWithOutSignature("eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1aWQiOiIxIiwidXBob25lIjoiMTg1MDI5OTk1MjIiLCJleHAiOjE2ODI0MzIyNDh9.u7GcbU0W4Yxz2GiRgbH8wwwubuTYtbxudd7djEUKH24"));

        System.out.println(autoContract("eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1aWQiOiIxIiwidXBob25lIjoiMTg1MDI5OTk1MjIiLCJleHAiOjE2ODI1MjU0NDN9.ZXTmALLMh56rfWyn-xXB2sU-FOIuKuwmBphSKzU5jf4"));
    }
}
